package com.gdufe.firesafe.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gdufe.firesafe.dao.UserDao;
import com.gdufe.firesafe.exception.RRException;
import com.gdufe.firesafe.model.constants.RoleConstant;
import com.gdufe.firesafe.model.dto.LoginDTO;
import com.gdufe.firesafe.model.dto.RegisterDTO;
import com.gdufe.firesafe.model.dto.ResetDTO;
import com.gdufe.firesafe.model.dto.UpdatePersonalInfoDTO;
import com.gdufe.firesafe.model.entity.HouseEntity;
import com.gdufe.firesafe.model.entity.InspectorEntity;
import com.gdufe.firesafe.model.entity.OwnerEntity;
import com.gdufe.firesafe.model.entity.UserEntity;
import com.gdufe.firesafe.model.vo.InspectorLoginVO;
import com.gdufe.firesafe.model.vo.LoginVO;
import com.gdufe.firesafe.model.vo.OwnerLoginVO;
import com.gdufe.firesafe.service.HouseService;
import com.gdufe.firesafe.service.InspectorService;
import com.gdufe.firesafe.service.OwnerService;
import com.gdufe.firesafe.service.UserService;
import com.gdufe.firesafe.utils.PageUtils;
import com.gdufe.firesafe.utils.Query;
import com.gdufe.firesafe.utils.TokenUtils;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service("userService")
//全参的构造函数，用于构造注入
@AllArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {
    private OwnerService ownerService;
    private InspectorService inspectorService;
    private HouseService houseService;

    //分页查询
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<UserEntity> page = this.page(
                new Query<UserEntity>().getPage(params),
                new QueryWrapper<UserEntity>()
        );

        return new PageUtils(page);
    }

    //注册
    @Override
    public void register(RegisterDTO registerDTO) {
        //检验合法性
        if (StrUtil.isBlank(registerDTO.getUserName()) || StrUtil.isBlank(registerDTO.getPassword())
                || StrUtil.isBlank(registerDTO.getRole()) || StrUtil.isBlank(registerDTO.getName())
                || StrUtil.isBlank(registerDTO.getPhone())) {
            throw new RRException("数据输入不合法");
        }
        //业主要SelectedHouse，检查员要SelectedBuilding
        String role=registerDTO.getRole();
        if(role.equals(RoleConstant.OWNER)){
            if(registerDTO.getSelectedHouse().size()!=3){
                throw new RRException("数据输入不合法");
            }
            if(registerDTO.getSelectedBuilding()!=null){
                throw new RRException("数据输入不合法");
            }
        }else if(role.equals(RoleConstant.INSPECTOR)){
            if(registerDTO.getSelectedHouse().size()!=0){
                throw new RRException("数据输入不合法");
            }
            if(registerDTO.getSelectedBuilding()==null){
                throw new RRException("数据输入不合法");
            }
        }else{
            throw new RRException("数据输入不合法");
        }
        //用户名不能重复
        QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name", registerDTO.getUserName());
        if (this.getOne(queryWrapper) != null) {
            throw new RRException("用户名已存在");
        }

        Integer roleId;
        //如果是业主
        if (registerDTO.getRole().equals(RoleConstant.OWNER)) {
            //调用业主模块,新增业主
            OwnerEntity owner = new OwnerEntity();
            owner.setName(registerDTO.getName());
            owner.setPhone(registerDTO.getPhone());
            owner.setEmail(registerDTO.getEmail());
            owner.setBuildingId(registerDTO.getSelectedHouse().get(0));
            owner.setFloorId(registerDTO.getSelectedHouse().get(1));
            owner.setHouseId(registerDTO.getSelectedHouse().get(2));
            ownerService.save(owner);
            roleId=owner.getId();
            if (roleId == null) {
                throw new RRException("新增业主失败");
            }
        } else if (registerDTO.getRole().equals(RoleConstant.INSPECTOR)) {
            //如果是安全检查员，新增检查员
            InspectorEntity inspector = new InspectorEntity();
            inspector.setName(registerDTO.getName());
            inspector.setPhone(registerDTO.getPhone());
            inspector.setBuildingId(registerDTO.getSelectedBuilding());
            inspectorService.save(inspector);
            roleId = inspector.getId();
            if (roleId == null) {
                throw new RRException("新增检查员失败");
            }
        } else {
            throw new RRException("数据输入不合法");
        }
        //对密码进行Bcrypt加密
        String hashpw = BCrypt.hashpw(registerDTO.getPassword());
        //新增用户
        UserEntity userEntity = new UserEntity();
        userEntity.setRoleId(roleId);
        userEntity.setUserName(registerDTO.getUserName());
        userEntity.setPassword(hashpw);
        userEntity.setRole(registerDTO.getRole());
        userEntity.setCreateTime(new Date());
        userEntity.setUpdateTime(new Date());
        this.save(userEntity);
    }

    //登录
    @Override
    public LoginVO login(LoginDTO loginDTO) {
        //检验数据合法性
        if (StrUtil.isBlank(loginDTO.getUserName()) || StrUtil.isBlank(loginDTO.getPassword()) ) {
            throw new RRException("数据输入不合法");
        }
        //查找用户
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getUserName, loginDTO.getUserName());
        UserEntity user = this.getOne(wrapper);
        //检验用户名
        if (user == null) {
            throw new RRException("用户名或密码错误");
        }
        //输入的密码与数据库的Bcrypt密文进行校验
        if (!BCrypt.checkpw(loginDTO.getPassword(),user.getPassword())) {
            throw new RRException("用户名或密码错误");
        }
        //根据user查角色相关信息
        LoginVO vo=getRoleInfo(user);
        //生成token
        String token = TokenUtils.createToken(user.getId()+"", user.getPassword());
        vo.setToken(token);
        //返回当前登录用户
        return vo;
    }

    //根据user查角色相关信息
    @Override
    public LoginVO getRoleInfo(UserEntity user) {
        LoginVO vo;
        //根据角色查角色相关信息
        if(user.getRole().equals(RoleConstant.OWNER)){
            vo=new OwnerLoginVO();
            OwnerEntity owner = ownerService.getById(user.getRoleId());
            ((OwnerLoginVO) vo).setName(owner.getName());
            ((OwnerLoginVO) vo).setEmail(owner.getEmail());
            //获取房屋坐标，即三个id
            List<Integer> houseCoordinate =new ArrayList<>();
            houseCoordinate.add(owner.getBuildingId());
            houseCoordinate.add(owner.getFloorId());
            houseCoordinate.add(owner.getHouseId());
            ((OwnerLoginVO) vo).setHouseCoordinate(houseCoordinate);
            ((OwnerLoginVO) vo).setPhone(owner.getPhone());
//            BeanUtil.copyProperties(r.get("owner"),vo,"id");
        }else if(user.getRole().equals(RoleConstant.INSPECTOR)){
            vo=new InspectorLoginVO();
            InspectorEntity inspector = inspectorService.getById(user.getRoleId());
            ((InspectorLoginVO) vo).setPhone(inspector.getPhone());
            ((InspectorLoginVO) vo).setName(inspector.getName());
            //获取楼栋id
            ((InspectorLoginVO) vo).setBuildingId(inspector.getBuildingId());
            ((InspectorLoginVO) vo).setPhoto(inspector.getPhoto());
//            BeanUtil.copyProperties(r.get("inspector"),vo,"id");
        }else{
            vo=new LoginVO();
        }
        BeanUtil.copyProperties(user, vo);
        return vo;
    }

    //获取当前登录用户个人信息，包括角色相关信息
    @Override
    public LoginVO getPersonalInfo(UserEntity user) {
        return getRoleInfo(user);
    }

    @Override
    public void updatePersonalInfo(UpdatePersonalInfoDTO updateInfo,UserEntity currentUser) {
        //修改用户表
        //用户名不能重复，若用户名有修改则检查
        if(!currentUser.getUserName().equals(updateInfo.getUserName())){
            LambdaQueryWrapper<UserEntity> wrapper=new LambdaQueryWrapper<>();
            wrapper.eq(UserEntity::getUserName,updateInfo.getUserName());
            UserEntity userEntity = baseMapper.selectOne(wrapper);
            if(userEntity!=null){
                throw new RRException("用户名已存在");
            }
            currentUser.setUserName(updateInfo.getUserName());
        }
        currentUser.setAvatar(updateInfo.getAvatar());
        baseMapper.updateById(currentUser);

        //修改角色相关信息
        if(!currentUser.getRole().equals(updateInfo.getRole())){
            throw new RRException("数据输入不合法");
        }
        if(currentUser.getRole().equals(RoleConstant.OWNER)){
            OwnerEntity owner=ownerService.getById(currentUser.getRoleId());
            owner.setName(updateInfo.getName());
            owner.setPhone(updateInfo.getPhone());
            owner.setEmail(updateInfo.getEmail());
            //更改业主的房屋
            Integer houseId = updateInfo.getHouseCoordinate().get(2);
            Integer floorId = updateInfo.getHouseCoordinate().get(1);
            Integer buildingId = updateInfo.getHouseCoordinate().get(0);
            HouseEntity house = houseService.getById(houseId);
            if(house==null){
                throw new RRException("数据输入不合法");
            }
            if(!house.getFloorId().equals(floorId)){
                throw new RRException("数据输入不合法");
            }
            if(!house.getBuildingId().equals(buildingId)){
                throw new RRException("数据输入不合法");
            }
            owner.setBuildingId(buildingId);
            owner.setFloorId(floorId);
            owner.setHouseId(houseId);
            ownerService.updateById(owner);
        }else if(updateInfo.getRole().equals(RoleConstant.INSPECTOR)){
            InspectorEntity inspector=inspectorService.getById(currentUser.getRoleId());
            inspector.setName(updateInfo.getName());
            inspector.setPhone(updateInfo.getPhone());
            inspector.setPhoto(updateInfo.getPhoto());
            inspector.setBuildingId(updateInfo.getBuildingId());
            inspectorService.updateById(inspector);
        }else {}
    }

    @Override
    public void resetPassword(ResetDTO resetDTO) {
        String userName = resetDTO.getUserName();
        boolean success = lambdaUpdate().eq(UserEntity::getUserName, userName).set(UserEntity::getPassword, BCrypt.hashpw("123")).update();
        if(!success){
            throw new RRException(500,"重置密码出错");
        }
    }

}
